package com.glink.manage.service.scheduled;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.manage.domain.PersonManageBean;
import com.glink.manage.domain.SilentResultBean;
import com.glink.manage.domain.SilentResultDetailBean;
import com.glink.manage.ftp.FTPUtils;
import com.glink.manage.service.*;
import com.glink.manage.vo.silentresult.SilentResultAnalysisVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : qiushaoshan
 * @create 2024/8/13 14:27
 */
@Service
@Slf4j
public class AutoService {

    @Autowired
    private SilentResultService silentResultService;

    @Autowired
    private SilentResultDetailService silentResultDetailService;
    
    @Autowired
    private FTPUtils ftpUtils;
    
    @Autowired
    private AiService aiService;

    @Autowired
    private ConstructionWorkAccessMonadService constructionWorkAccessMonadService;
    
    @Autowired
    private ConstructionWorkSiteService constructionWorkSiteService;
    
    @Autowired
    private BarriersService barriersService;

    @Autowired
    private PersonManageService personManageService;

    @Autowired
    private BlacklistService blacklistService;
    
    @Autowired
    private BarrierGateService barrierGateService;
    
    @Autowired
    private UserService userService;
    
    private AnalysisActuator analysisActuator;
    
    private LocalDateTime localDateTime;
    
    // 黑名单的年龄标准
    @Value("${blacklist.age.level:60}")
    private Integer blacklistAgeLevel;

    @Value("${isDelFile:false}")
    private Boolean isDelFile;
    
    @Scheduled(cron = "${cron.warn.analysis:0/30 * * * * ? }")
//    @PostConstruct
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void warnAnalysis() {
        log.info("定时任务分析图片，开始分析");

        LocalDateTime endTime = LocalDateTime.now();

        List<SilentResultAnalysisVO> analysisVOList = silentResultService.findToBeAnalyzedByCreateTimeBetween(localDateTime, endTime);
        if(CollectionUtils.isNotEmpty(analysisVOList)){
            log.info("start:{}, end:{}", localDateTime, endTime);
            AnalysisActuator actuator = getAnalysisActuator();
            if(actuator != null){
                analysisVOList.forEach(actuator::addStartTaskSignal);
            }

            localDateTime = endTime;
        }
       
        log.info("定时任务分析图片，生成结束");

        log.info("定时任务处理结果信息，开始处理");
        silentResultService.updateBaseInfoByError();
        log.info("定时任务处理结果信息，处理结束");
    }

    /**
     * 开始分析
     */
    public void startAnalysisOnStartUp() {

        AnalysisActuator actuator = getAnalysisActuator();
        localDateTime = LocalDateTime.now();
        actuator.startAnalysisOnStartUp(localDateTime);
    }

    /**
     * 初始化执行器
     * @return 执行器
     */
    private AnalysisActuator getAnalysisActuator(){
        if(analysisActuator == null){
            analysisActuator = new AnalysisActuator(silentResultService, ftpUtils, aiService);
            analysisActuator.start();
        }
        return analysisActuator;
    }

    /**
     * 和前端交互的websocket定时统计
     */
    @Scheduled(cron = "${cron.warn.count:0/5 * * * * ? }")
    public void warnCount() {
        log.info("定时任务，统计数量，开始统计");
        log.debug("定时任务统计告警数，开始统计");
        silentResultService.countWebSocketReadWarn();
        log.debug("定时任务统计告警数，统计结束");

        log.debug("定时任务统计待审批数，开始统计");
        constructionWorkAccessMonadService.countPendingApproval();
        log.debug("定时任务统计待审批数，统计结束");

        log.debug("定时任务统计待处理违章数，开始统计");
        silentResultService.countPendingViolationHandling();
        log.debug("定时任务统计待处理违章数，统计结束");
        
        log.info("定时任务，统计数量，结束统计");
    }

    /**
     * 补充分析遗漏分析的图片
     */
    @Scheduled(cron = "${cron.warn.compensate:0 0 2 * * ?  }")
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void compensate() {
        log.info("定时任务，补充逻辑，将漏分析图片进行分析，开始分析");
        AnalysisActuator actuator = getAnalysisActuator();
        LocalDateTime nowDate = LocalDateTime.now();
        nowDate = LocalDateTimeUtil.beginOfDay(nowDate);
        actuator.startAnalysisOnStartUp(nowDate);
        log.info("定时任务，补充逻辑，将漏分析图片进行分析，结束分析");
    }

    /**
     * 统计设备离线
     */
    @Scheduled(cron = "${cron.equip.online:0 0/1 * * * ?  }")
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void equipOnlineStatus() {
        barriersService.updateBarriersOnlineStatus();
    }

    /**
     * 校验场站授权
     */
    @Scheduled(cron = "${cron.site.check_authorize:0 0 0,1 * * ?  }")
//    @Scheduled(cron = "${cron.site.check_authorize:0 0 0/1 * * ? }")
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void checkSiteAuthorize() {
        constructionWorkSiteService.checkSiteAuthorize();
    }

    /**
     * 定时检查所有人员信息，如>=60岁，自动列入黑名单
     */
    @Scheduled(cron = "${cron.check_personManageInfo:0 0 0 * * ?}")
    public void maintainBlacklistScheduled (){
        List<PersonManageBean> personManageBeanList= personManageService.lambdaQuery()
                .eq(PersonManageBean::getIfDelete,BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02).list();
        if (CollectionUtils.isNotEmpty(personManageBeanList)){
            personManageBeanList.parallelStream().forEach(personManageBean -> {
                if (StringUtils.isNotBlank(personManageBean.getCard()) ){
                    String birthDateStr = personManageBean.getCard().substring(6, 14); // 提取第7到14位
                    int year = Integer.parseInt(birthDateStr.substring(0, 4));
                    int month = Integer.parseInt(birthDateStr.substring(4, 6));
                    int day = Integer.parseInt(birthDateStr.substring(6, 8));
                    LocalDate birthDate= LocalDate.of(year, month, day);
                    int years = Period.between(birthDate, LocalDate.now()).getYears();
                    if (years >= blacklistAgeLevel){
                        Boolean aBoolean = blacklistService.saveByIdNumberAndTypeAndUserName(personManageBean.getCard(), BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01, personManageBean.getName(), personManageBean.getObjId(), BaseCodeConstants.CodeType_AddBlackListActionType.KEY_AddBlackListActionType01, String.format("人员%s的年龄已经超过了%s岁,系统自动添加至黑名单", personManageBean.getName(), blacklistAgeLevel));

                        if(Objects.nonNull(aBoolean) && aBoolean && StringUtils.isNotBlank(personManageBean.getAccountObjId())){
                            // 用户账号添加禁用
                            userService.updateStatusByIdAndStatus(BaseCodeConstants.CodeType_UserStatus.KEY_UserStatus02, personManageBean.getAccountObjId(), BaseCodeConstants.CodeType_UserStatus.KEY_UserStatus01);
                        }
                    }
                }
            });
        }
    }

    /**
     * 下发道闸数据
     */
    @Scheduled(cron = "${cron.barrier_gates.issued:0 0 23 * * ? }")
    public void issuedBarrierGatesData(){
        log.info("定时任务，下发数据到道闸，开始下发");
        LocalDateTime nowDate = LocalDateTime.now();
        nowDate = nowDate.plusDays(1L);
        
        barrierGateService.taskIssuedDataToBarrierGates(nowDate);
        log.info("定时任务，下发数据到道闸，结束下发");
    }


    @Scheduled(cron = "${cron.delFile:0 0 2 * * ? }")
    public void deleteFile() {
        if(isDelFile){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date()); // 设置当前日期
            calendar.add(Calendar.DAY_OF_MONTH, -14); // 往前加5天
            Date newDate = calendar.getTime();

            List<SilentResultBean> resultBeanList = silentResultService.lambdaQuery().le(SilentResultBean::getCreateTime, newDate).list();
            if(CollectionUtils.isNotEmpty(resultBeanList)){
                List<String> resultIdList = resultBeanList.stream().map(SilentResultBean::getObjId).collect(Collectors.toList());
                List<String> analysisFilePathList = resultBeanList.stream().map(SilentResultBean::getAnalysisFilePath).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
                List<String> filePathList = resultBeanList.stream().map(SilentResultBean::getFilePath).filter(StringUtils::isNotEmpty).collect(Collectors.toList());

                if(CollectionUtils.isNotEmpty(filePathList)){
                    filePathList.forEach(filePath -> {
                        try {
                            ftpUtils.deleteFile(filePath);
                        } catch (Exception e) {
                            log.error("定时任务，文件删除失败：{}", filePath, e);
                        }
                    });
                }
                
                if(CollectionUtils.isNotEmpty(analysisFilePathList)){
                    analysisFilePathList.forEach(filePath -> {
                        try {
                            ftpUtils.deleteFile(filePath);
                        } catch (Exception e) {
                            log.error("定时任务，文件删除失败：{}", filePath, e);
                        }
                    });
                }

                List<List<String>> partition = Lists.partition(resultIdList, 1000);
                partition.forEach(obj -> {
                    silentResultDetailService.lambdaUpdate().in(SilentResultDetailBean::getResultObjId, obj).remove();
                    silentResultService.lambdaUpdate().in(SilentResultBean::getObjId, obj).remove();
                });
            }
        }
    }
}
